#include "MeleeWeapon.h"
#include "Game.h"
#include "Renderer.h"
#include "StringLib.h"
#include "Util.h"

MeleeWeapon::MeleeWeapon(MeleeWeaponType weaponType, MaterialType materialType, MeleeWeaponPrefix prefix, MeleeWeaponSuffix suffix, bool highQuality) : Weapon(GT_IT_MELEE_WEAPON, highQuality) {
	m_types[TH_MELEE_WEAPON_TYPE] = weaponType;
	m_materialType = materialType;
	m_prefix = prefix;
	m_suffix = suffix;
	const MeleeWeaponInfo& info = g_objectDatabase->getMeleeWeaponInfo(weaponType);
	m_types[TH_WEAPON_FAMILY] = info.family;
	m_gripType = info.grip;
	calculateStats(info);
}

MeleeWeapon::MeleeWeapon(std::ifstream& file) : Weapon(GT_IT_MELEE_WEAPON, file) {
	int* tokens = Util::intSplit(file);
	m_types[TH_MELEE_WEAPON_TYPE] = tokens[0];
	const MeleeWeaponInfo& info = g_objectDatabase->getMeleeWeaponInfo(MeleeWeaponType(tokens[0]));
	m_types[TH_WEAPON_FAMILY] = info.family;
	m_gripType = info.grip;
	calculateStats(info, true);
	m_prefix = MeleeWeaponPrefix(tokens[1]);
	m_suffix = MeleeWeaponSuffix(tokens[2]);
	m_materialType = MaterialType(tokens[3]);
	delete[] tokens;
}

MeleeWeapon::~MeleeWeapon() {
}

void MeleeWeapon::save(std::ofstream& file) const {
	file << getType(TH_GENERIC_TYPE) << "\n";
	Weapon::save(file);
	file << getType(TH_MELEE_WEAPON_TYPE) << " " << m_prefix << " " << m_suffix << " " << " " << m_materialType << "\n";
}

void MeleeWeapon::calculateStats(const MeleeWeaponInfo& info, bool defaultsOnly) {
	m_defaultNumDice = info.numDie;
	m_defaultDiceSides = info.diceSides;
	m_defaultAttackBonus = info.attackBonus;
	m_defaultAccuracy = info.accuracy;
	m_defaultSpeed = info.speed;
	m_weight = info.weight;

	switch(m_materialType) {
	case MT_OAK:
		m_defaultNumDice--;
		m_defaultAttackBonus -= 2;
		m_defaultSpeed -= 20;
		m_weight -= m_weight / 20;
		break;
	case MT_WALNUT:
		m_defaultNumDice--;
		m_defaultAttackBonus--;
		m_defaultSpeed -= 10;
		m_weight -= m_weight / 10;
		break;
	case MT_COPPER:
		m_defaultNumDice--;
		break;
	case MT_IRON:
		m_defaultAttackBonus++;
		m_defaultSpeed += 10;
		m_weight += m_weight / 10;
		break;
	case MT_BRONZE:
		m_defaultAttackBonus++;
		break;
	case MT_BRASS:
		m_defaultNumDice++;
		m_defaultAttackBonus++;
		break;
	}

	if(!defaultsOnly) {
		m_numDice = m_defaultNumDice;
		m_diceSides = m_defaultDiceSides;
		m_attackBonus = m_defaultAttackBonus;
		m_accuracy = m_defaultAccuracy;
		m_speed = m_defaultSpeed;
	}

	m_defaultNumDice = std::max(1, m_defaultNumDice);
	m_defaultDiceSides = std::max(1, m_defaultDiceSides);

	if(!defaultsOnly) {
		switch(m_prefix) {
		case MWP_DULL:
			m_diceSides -= 2;
			break;
		case MWP_HEAVY:
			m_speed += 20;
			m_weight *= 2;
			break;
		case MWP_SHARP:
			m_diceSides++;
			break;
		case MWP_BRUTAL:
			m_numDice += 2;
			break;
		case MWP_FINE:
			m_accuracy++;
			m_attackBonus++;
			m_weight -= m_weight / 5;
			break;
		case MWP_MASTERWORK:
			m_accuracy += 2;
			m_attackBonus += 2;
			m_weight -= m_weight / 10;
			break;
		}

		switch(m_suffix) {
		case MWS_OF_SLOTH:
			m_speed += 50;
			break;
		case MWS_OF_WRATH:
			m_numDice += 2;
			m_diceSides += 2;
			m_accuracy += 2;
			m_attackBonus += 2;
			break;
		case MWS_OF_PRIDE:
			m_accuracy -= 3;
		}

		if(m_highQuality) {
			m_numDice++;
			m_diceSides++;
			m_accuracy++;
			m_attackBonus++;
			m_speed -= 10;
		}
	
		m_numDice = std::max(m_numDice, 1);
		m_diceSides = std::max(m_diceSides, 1);
	}
}

void MeleeWeapon::render(float x, float y) {
	g_renderer->render(*this, x, y);
}

std::string MeleeWeapon::getItemName(int mod) const {
	std::string output = "";
	if(m_statusIdentified)
		output += g_stringLib->getMiscString(MST_STATUS, m_status) + " ";

	if(m_equippableIdentified) {
		if(m_highQuality)
			output += "high quality ";
		if(m_prefix != MWP_NONE)
			output += g_stringLib->getMiscString(MST_MELEE_WEAPON_PREFIX, m_prefix) + " ";
	} else {
		if(isEnchanted())
			output += "enchanted ";
	}
	output += g_stringLib->getMiscString(MST_MATERIAL, m_materialType) + " " + getBasicName();
	if(m_equippableIdentified && m_suffix)
		output += " " + g_stringLib->getMiscString(MST_MELEE_WEAPON_SUFFIX, m_suffix);
	if(m_equippableIdentified)
		output += " (" + Util::intToString(m_numDice) + "d" + Util::intToString(m_diceSides) + "" + Util::signIntToString(m_attackBonus) + ", " + Util::signIntToString(m_accuracy) + ", " + Util::intToString(m_speed) + "%)";
	else
		output += " (" + Util::intToString(m_defaultNumDice) + "d" + Util::intToString(m_defaultDiceSides) + "" +
			Util::signIntToString(m_defaultAttackBonus) + ", " + Util::signIntToString(m_defaultAccuracy) + ", " + Util::intToString(m_defaultSpeed) + "%)";
	return output;
}

bool MeleeWeapon::isEnchanted() const {
	return m_prefix != MWP_NONE || m_suffix != MWS_OF_NONE || m_highQuality;
}

void MeleeWeapon::logDetails(TextLog& log) const {
	Weapon::logDetails(log);
	log.addBlankLine();
	log.addLine(g_stringLib->getTextString(ST_WEAPON_MATERIAL, g_stringLib->getMiscString(MST_MATERIAL, m_materialType).c_str()));
	if(m_equippableIdentified) {
		if(m_prefix != MWP_NONE)
			log.addLine(g_stringLib->getMiscString(MST_MELEE_WEAPON_PREFIX, m_prefix));
		if(m_suffix != MWS_OF_NONE)
			log.addLine(g_stringLib->getMiscString(MST_MELEE_WEAPON_SUFFIX, m_suffix));
	}
}
